package com.yanxin.admin.service.impl;

import cn.hutool.core.util.StrUtil;
import com.yanxin.admin.domain.LdapConfig;
import com.yanxin.admin.domain.LdapUser;
import com.yanxin.admin.domain.User;
import com.yanxin.admin.dto.LoginUserDTO;
import com.yanxin.admin.repository.LdapConfigRepository;
import com.yanxin.admin.repository.LdapUserRepository;
import com.yanxin.admin.repository.UserRepository;
import com.yanxin.admin.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.LdapContextSource;
import org.springframework.ldap.filter.EqualsFilter;
import org.springframework.ldap.query.LdapQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;

/**
 * @program spring-cloud-example
 * @description:
 * @author: LiuYanXin
 * @create: 2020-12-24 14:18
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private LdapUserRepository ldapUserRepository;

    @Autowired
    private LdapTemplate ldapTemplate;

    @Autowired
    private LdapConfigRepository ldapConfigRepository;

    @Autowired
    private Executor asyncExecutor;

    @Autowired
    private ScheduledExecutorService scheduleExecutor;


    @Override
    @Transactional(readOnly = true)
    public User selectByName(String username) {

        LdapConfig ldapConfig = ldapConfigRepository.findById(1L).get();
        LdapContextSource source = new LdapContextSource();
        source.setBase("DC=jktest,DC=cn");
        source.setUrl(ldapConfig.getUrls());
        source.setPassword("Adadmin@jk888");
        source.setUserDn("administrator");
        source.afterPropertiesSet();
        ldapTemplate.setContextSource(source);
        List<LdapUser> users = ldapTemplate.find(LdapQueryBuilder.query()
                .where("cn").is("wangwu")
                .or("sAMAccount1Name").is("ww")
                .or("userPrincipalName").is("w1w@jktest.cn"), LdapUser.class);

        /*return userRepository.findByUsername(username)
                .orElseThrow(() -> new IllegalArgumentException("未找到用户:" + username));*/
        return User.builder()
                .username("root").build();
    }

    @Caching(
            put = {@CachePut(value = "userCache", key = "#user.id")},
            evict = {@CacheEvict(value = "userListCache", allEntries = true)}
    )
    // @GlobalTransactional(name = "goods_tx_group")
    @Override
    @Transactional(rollbackFor = Exception.class)
    public User insertUser(User user) {

        // 开启异步线程插入数据
        userRepository.save(user);
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return user;

    }

    @Override
    public User saveOrUpdate(User user) {
        // 开启异步线程插入数据
        userRepository.save(user);
        return user;
    }


    @Override
    // @Cacheable(value = "userCache", key = "#id")
    @Transactional(readOnly = true)
    public User getUserById(String id) {
        long start = System.currentTimeMillis();
        while (true) {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            User user = userRepository.findById(NumberUtils.toLong(id))
                    .orElseThrow(() -> new IllegalArgumentException("未查找到该用户: " + id));
            if (StrUtil.isNotEmpty(user.getNickname())) {
                return user;
            }
            long end = System.currentTimeMillis();
            log.info("开始: {}, 结束: {}", start, end);
            // 循环终止
            if (end - start > 5000) {
                log.info("循环终止");
                break;
            }
            log.info("线程名称: {},使用时间: {}", Thread.currentThread().getName(), System.currentTimeMillis() - start);
        }
        return null;

    }

    @Override
    @Cacheable(value = "userListCache")
    public List<User> getAll() {

        return userRepository.findAll();
    }

    @Override
    public Boolean login(LoginUserDTO loginUserDTO) {

        Optional<LdapUser> opt = ldapUserRepository.findByCnAndUserPrincipalName("wangwu", "ww@jktest.cn");
        LdapUser user = opt.get();
        EqualsFilter filter = new EqualsFilter("sAMAccountName", user.getSAMAccountName());
        return ldapTemplate.authenticate("", filter.toString(), "123qweASD");
    }
}
